home *** CD-ROM | disk | FTP | other *** search
/ PC Format (UK) 124 / pcfcd124-a.iso / Trial Software / BlitzBasic / Rift2001-05-16 / Rift2 / tutorial2d-complete-with-tutorial1.bb < prev    next >
Encoding:
Text File  |  2001-05-16  |  58.2 KB  |  1,081 lines

  1. AppTitle "Celestial Rift - Version 1.1 (C)2001 Myke P" ;what this program will be called in MICROSOFT WINDOWS.
  2.  
  3. ;This makes two CONSTants. These are values which will NOT change at any point in the program, so we set their values now.
  4. Const SCREEN_WIDTH = 800
  5. Const SCREEN_HEIGHT = 600
  6. ;This is the code which tells Blitz what Display Resolution to use on the Graphics Card. The "GRAPHICS" command should always be placed before you do
  7. ;*anything* image-related in your program
  8. Graphics SCREEN_WIDTH,SCREEN_HEIGHT,0,1    ;start the graphics mode at SCREEN_WIDTH by SCREEN_HEIGHT, let Blitz choose the depth (,0) and run full screen (,1)
  9.  
  10. ;more program CONSTants..
  11. Const GAME_AREA_X = 50000    ;these two set the size of the map. You *should* keep them the same, 'cos the radar is square
  12. Const GAME_AREA_Y = 50000    ;but technically, you can change the values to anything you like! ;)
  13. ;the following constants are keyboard "SCAN" codes. Every key on the keyboard has a number. You can get the full list in your Blitz manual.
  14. Const KEY_CLOCKWISE = 25    ;(p)    
  15. Const KEY_ANTICWISE = 24    ;(o)
  16. Const KEY_SPEEDUP = 16        ;(q)
  17. Const KEY_SPEEDDOWN = 30    ;(a)
  18. Const KEY_FIRE = 57            ;(Space)
  19. Const KEY_HYPER = 2            ;(1)
  20. Const KEY_BOOST = 50        ;(m)
  21. Const KEY_CLOAK = 46        ;(c)
  22. Const KEY_QUIT = 1            ;(Escape)
  23. Const KEY_PAUSE = 7            ;(Number 6 on the main keyboard)
  24. Const KEY_DEBUG = 59        ;(F1)
  25. Const KEY_SAVESCREEN = 88    ;(F12)
  26. ;the following constants affect the way the game plays. Feel free to mess with the values..
  27. Const INCR_ROTATE# = 5                ;.. but DON'T touch this, otherwise the game will crash (I only drew the animation frames for 5 degree intervals!)
  28. Const INCR_SPEED# = 0.5
  29. Const INCR_SLOW# = 0.125
  30. Const INCR_BOOSTERS_UP# = 0.025
  31. Const INCR_BOOSTERS_DOWN# = .75
  32. Const INCR_CLOAK_UP#= 0.0125
  33. Const INCR_CLOAK_DOWN# = .25 
  34. Const SPEED_MAX = 25
  35. Const SPEED_MIN = -5
  36.  
  37. ;set up changable variables for game/menu (with initial values, if you like - i.e.: you could just as soon as set them later!)
  38. Global FLAG_GAMEON
  39. Global FLAG_MENUON
  40. Global FLAG_PAUSE
  41. Global FLAG_SAVESCREEN = 0
  42. Global FLAG_DEBUG = 0
  43. Global FLAG_GAMESTARTER
  44. Global PLAYER_SHIELD#
  45. Global PLAYER_BOOSTERS#
  46. Global PLAYER_CLOAK#
  47. Global PLAYER_JUMPS
  48. Global PLAYER_SPEED#
  49. Global PLAYER_ANGLE#
  50. Global PLAYER_X#
  51. Global PLAYER_Y#
  52. Global PLAYER_SCORE
  53. Global HI_SCORE
  54.  
  55. Global timer
  56. Global frames
  57. Global starson
  58. Global menu_frame
  59. Global menu_accept_quit
  60. Global game_pause_frame
  61. Global game_accept_pause
  62. Global game_pause_stat
  63. Global hypercount#        ;a "#" symbol after the variable name means it can hold a FLOATING POINT number, i.e.: 190.1234
  64. Global pausecount        ;without the "#" symbol, the variable is, by default, an INTEGER (Whole) number, i.e.: 190
  65. Global cloakon#            ;use the symbols when you are *sure* that you want it to hold specific types of data:
  66. Global frame1            ;# - floating point
  67. Global frame2            ;% - integer (whole number)
  68. Global frame3            ;$ - string (text, i.e.: "MYKE 12345"
  69. Global frame4            ;
  70. Global frame5
  71. Global frame6
  72. Global frame7
  73. Global frame8
  74. Global tempstr$
  75.  
  76. timer = CreateTimer(50) ;create a timer set at 50ms (game speed) - play with this to see how you can increase or decrease the speed of the game.
  77.                         ;this should be set at a speed which will look near enough the same on *every* PC it will be played on.
  78.                         ;My PC (a 733MHz PIII with an nVidia GeForce card) will handle upwards of 150 frames per second, quite happily
  79.                         ;but 'lesser' machines will not. 50, therefore, is quite sensible For a game of this nature, who's minimum system spec
  80.                         ;will be something like a PII 300MHz machine (i.e.: Blitz Basic's minimum spec!)
  81.  
  82. ;NOTE: there's no need to organise your variable declarations, as I have here, into sections. They can appear in any order you like, before the main program begins.
  83. ;I just do this, 'cos it looks right professional! :))))
  84.  
  85. ;picture/animation (and related) variables
  86. Dim game_stars(5)            ;these 3 are ARRAYS. An array is automatically Global, but requires the Keyword (Yellow bit) DIM instead. This means "Dimension".
  87. Dim game_icons(4)            ;the arrays have single dimensions (imagine one straight line of boxes, each that can contain a single variable) 0 to.. (the number in brackets)
  88. Global game_icon_dot
  89. Global game_player
  90. Global game_player_frame
  91. Global game_player_dot
  92. Global game_bullet_player
  93. Global game_gameover
  94. Global game_paused
  95. Global menu_hiscore
  96. Global menu_lastscore
  97. Global menu_scorefont
  98. Global menu_start
  99. Global menu_start_stat
  100. Global menu_logo
  101. Global menu_credit
  102. Global menu_guildhall
  103. Global menu_thanks
  104. Global menu_quit
  105. Global menu_ship1
  106. Global menu_ship2
  107. Global menu_ship_hor
  108. Global menu_ship_ver#
  109. Global menu_ship_type
  110.  
  111. ;Types are like Structures in C. You have a "Type" called whatever. Then you can make multiple versions of the type. Each version of the Type has the same properties, i.e.:
  112. ;a FISH (the Type) has EYES, MOUTH, SCALES And FINS (it's properties) - ALL FISH have these properties.
  113. ;a DOG (the Type) has EYES, MOUTH, FUR and TAIL (it's properties) - ALL DOGS have these properties (look like this.)
  114. Type stars                        ;create "Type" for parallex stars
  115.     Field depth,x#,y#            ;each star has a depth, x and y position
  116. End Type
  117.  
  118. Type icons                        ;same for icons
  119.     Field x#,y#,style,frame#
  120. End Type
  121.  
  122. ;this is for the bullets. I've used an array, rather than a type (which would have been just as good in this case) to show you how MULTIDIMENSIONAL arrays can work.
  123. Const bulletnum = 500
  124. Global bulletlimiter
  125. Global nextbullet = 0
  126. Dim bullets(bulletnum-1,7) ;create an array for 'bulletnum' (0 to bulletnum -1) on-screen bullets with 8 values per bullet:
  127.                         ;0 = bullet_x, 1 = bullet_y, 2 = bullet_angle, 3 = bullet_speed,
  128.                         ;4 = bullet_style, 5 = bullet_animframe, 6 = bullet_origin_x, 7 = bullet_origin_y
  129.                         ;we'll say that a bullet's style can also say whether or not it's in use, i.e.: 0 = off, 1 = player, 2 = enemy1
  130.  
  131.  
  132. ;this code makes 4 'objects' in a "Type" called "ICONS".
  133. For i = 1 To 4                    ;do this 1, 2, 3, 4 times
  134.     icon.icons = New icons        ;create a new icon
  135.     icon\style = i                ;the icon style for each new icon is equal to the increment of i (i.e.: 1, 2, 3 or 4!)
  136.     icon\frame = Int(Rnd(0,5))    ;create a random frame number between 0 and 5 for each new icon
  137. Next
  138.  
  139. menustars = SCREEN_HEIGHT/3 ;generate a number of stars, so that they look dense enough on all test resolutions
  140. starson = 1 ;tells the program to show the stars (see later)
  141. For i=0 To menustars                    ;create <menustars> number of stars in the STARS type
  142.     star.stars=New stars                ;add a new star for each increment of i
  143. Next
  144.  
  145. ;this code loads the image numbers into an array called "game_ stars", which we DIMmed earlier. It has 6 containers (0,1,2,3,4,5) but I'm only using 1 to 5!
  146. ;an "image number" is what Blitz uses to reference graphics held in the Video Memory, i.e.:
  147. ;1. Image number 12 is a picture of a flower.
  148. ;2. Make a variable called "flower_pic" = 12
  149. ;3. Wherever Blitz is told to draw "flower_pic", reference image number 12 in the Video Memory.
  150. game_stars(1) = LoadImage("GfxRes/backg-star-1.bmp")    ;container (1) in "game_stars" holds the image number for this picture ("GfxRes/backg-star-1.bmp")
  151. game_stars(2) = LoadImage("GfxRes/backg-star-2.bmp")    ;etc..
  152. game_stars(3) = LoadImage("GfxRes/backg-star-3.bmp")
  153. game_stars(4) = LoadImage("GfxRes/backg-star-4.bmp")
  154. game_stars(5) = LoadImage("GfxRes/backg-star-5.bmp")
  155. For i = 1 To 5
  156.     MaskImage game_stars(i),255,0,255    ;mask the images for each star, so that MAGENTA (255,0,255) is the transparent colour
  157. Next
  158.  
  159. ;similarly, this code loads the image numbers into an array called "game_icons"
  160. ;however, these are images that contain the frames of an Animation, so a different Load command is used.
  161. game_icons(1) = LoadAnimImage("GfxRes/icon-boost.bmp",32,32,0,6)    ;LoadAnimImage has the same structure as LoadImage, with additional numbers after the picture filename
  162. game_icons(2) = LoadAnimImage("GfxRes/icon-shield.bmp",32,32,0,6)    ;these are: Frame Width (pixels), Frame Height (pixels), Starting Framenumber (usually 0)
  163. game_icons(3) = LoadAnimImage("GfxRes/icon-cloak.bmp",32,32,0,6)    ;and the Number of Frames in the Image (as *you* would count them (in this case 6)
  164. game_icons(4) = LoadAnimImage("GfxRes/icon-jump.bmp",32,32,0,6)        ;have a look at the file "icon-boost" in Paint Shop Pro and see for yourself the 6 frames of animation.
  165. For i = 1 To 4
  166.     MaskImage game_icons(i),255,0,255    ;mask the images for each icon, so that MAGENTA (255,0,255) is the transparent colour
  167. Next
  168.  
  169. ;notice in the following code, we're loading (and MASKING) graphics in exactly the same way as before, but into regular variables instead of arrays.
  170. ;this next bit is all animations
  171. game_player = LoadAnimImage("GfxRes/player-ship.bmp",80,80,0,72) ;load in the 'sprite' for the player ship
  172. MaskImage game_player,255,0,255 ;mask the images for the player ship, so that MAGENTA (255,0,255) is the transparent colour
  173. game_bullet_player = LoadAnimImage("GfxRes/bullet-player.bmp",10,10,0,6)    ; the blue player bullet animation
  174. MaskImage game_bullet_player,255,0,255 ;mask the images
  175. ;these are all plain single-frame pictures
  176. ;menu piccies
  177. menu_logo = LoadImage("GfxRes/menu-logo.bmp")            ;the CELESTIAL RIFT logo
  178. menu_ship1 = LoadImage("GfxRes/menu-ship1.bmp")            ;the big player-type ship
  179. menu_ship2 = LoadImage("GfxRes/menu-ship2.bmp")            ;the big enemy type ship
  180. menu_guildhall = LoadImage("GfxRes/menu-guildhall.bmp")    ;the GUILDHALL message at the top
  181. menu_thanks = LoadImage("GfxRes/menu-thanks.bmp")        ;the THANKS message at the bottom
  182. menu_credit = LoadImage("GfxRes/menu-credit.bmp")        ;the CREDITS message below the logo
  183. menu_start = LoadImage("GfxRes/menu-start.bmp")            ;the "PRESS FIRE TO START" caption
  184. menu_quit = LoadImage("GfxRes/menu-quit.bmp")            ;the "(ESCAPE TO QUIT)" caption
  185. ;game piccies
  186. game_gameover = LoadImage("GfxRes/game-gameover.bmp")        ;the game over logo, which I tend to see a lot of.. :(
  187. game_paused = LoadImage("GfxRes/game-paused.bmp")            ;the paused logo
  188. game_player_dot = LoadImage("GfxRes/player-radardot.bmp")    ;radar dots for the player and bonus icons respectively
  189. game_icon_dot = LoadImage("GfxRes/icon-radardot.bmp")
  190. MaskImage menu_ship1,255,0,255            ;mask all the images.
  191. MaskImage menu_ship2,255,0,255            ;notice that it doesn't matter what order you do the masks in!
  192. MaskImage menu_credit,255,0,255
  193. MaskImage menu_guildhall,255,0,255        ;by the way, if when testing your program, you get the error message "IMAGE DOES NOT EXIST" at this point
  194. MaskImage menu_thanks,255,0,255            ;in the program, it's because the LOADIMAGE command above didn't find the file properly.
  195. MaskImage menu_start,255,0,255            ;This is usually either because; 1 - You've typed the wrong filename in the LOADIMAGE bit, or
  196. MaskImage menu_quit,255,0,255            ;2 - You've got the variable name wrong in the MASKIMAGE bit.
  197. MaskImage game_gameover,255,0,255
  198. MaskImage game_paused,255,0,255
  199.  
  200. ;Right! That's it, we've set up *everything* we're going to need from outside the program.
  201. menu_loop() ;start the proper program loop by 'calling' the function called "menu_loop()" - which, conveniently, is just coming up!!!
  202.  
  203. ;this function keeps the menu loop going.. It starts playing tunes and sets a couple of variables. 
  204. ;Then it goes into a never ending loop which carries out a sequence of checks and function calls.
  205. Function menu_loop() ;Start of the Function whose name is "menu_loop()"
  206.     FLAG_MENUON = 1 ;tells the program that the menu is running, for use in the REPEAT..FOREVER statement in a sec..
  207.     menu_ship_hor = (SCREEN_WIDTH/2)-(ImageWidth(menu_ship1)/2) ;this sets the starting horizontal position of the big ship on the menu
  208.     menu_ship_ver = SCREEN_HEIGHT+1    ;this sets the vertical starting position of the big ship on the menu at one pixel off the bottom of the screen.
  209.                                     ;notice that images are (by default) handled from the TOP-LEFT pixel, so, horizontally, I offset the value
  210.                                     ;to the left, by half the width of the ship image.
  211.     menu_ship_type = 1                ;set up some initial values for these counters
  212.     menu_frame = 1                    
  213.     menu_start_stat = 0
  214.     menu_accept_quit = 0
  215.     
  216.     Repeat        ;a REPEAT.. FOREVER loop will carry out the code in between for as long as the program is running..
  217.         If FLAG_MENUON = 1 Then    ;If the FLAG_MENUON flag is set to 1 then "do" the following..
  218.             menu_loop_update()    ;call function "menu_loop_update()"
  219.             ;this IF statement checks to see if the game music is playing (as it will be when you quit the game)
  220.         Else                                    ;if the FLAG_MENUON flag wasn't set to 1 then "do" the following..
  221.             End                                        ;END the program
  222.         End If
  223.     Forever    ;end of the REPEAT.. FOREVER loop
  224. End Function ;End of the function
  225.  
  226. ;"menu_loop_update()" checks for key-presses, alters position coordinates on the screen
  227. ;and various variables/flags for use in "menu_draw_update()" and the game functions too.
  228. ;in fact, you'll see that this has the same organisational structure as the proper game loop (albeit much less complex!)
  229. Function menu_loop_update()
  230.     frames = WaitTimer(timer) ;returns a value to "frames" for how many video screen refreshes (The MHz of your monitor) occured since the last call to our timer
  231.     For i = 1 To frames    ;update the screen positions for "frames" number of changes.. This enables drawing frames to be skipped on slower machines.
  232.         If KeyDown(KEY_QUIT)                ;If the user presses the "QUIT" button on the keyboard, then..
  233.             FlushKeys                        ;(when using SCAN CODES, flush the keyboard buffer after each successful "Have they pressed a particular key" question.)
  234.  
  235.             If menu_accept_quit = 1 Then    ;If the variable "menu_accept_quit" is 1, then set the FLAG_MENUON to 0.
  236.                 FLAG_MENUON = 0                ;back in the "menu_loop()" function, this will cause the program to end!
  237.             End If
  238.         End If
  239.  
  240.         If KeyDown(KEY_FIRE)                ;If the user presses the "FIRE" button on the keyboard, then..
  241.             FlushKeys
  242.             FLAG_DEBUG = 0                    
  243.             FLAG_GAMESTARTER = 1
  244.             hypercount = 102
  245.             FLAG_PAUSE = 0
  246.             game_loop()                            ;call the function called "game_loop()" (the game will run, but once it has ended, we'll find ourselves back here...)
  247.             
  248.             menu_ship_ver = SCREEN_HEIGHT+1
  249.             menu_frame = 1
  250.             menu_start_stat = 0
  251.             menu_accept_quit = 0                ;by setting this to 0, we'll stop the program ending by any surplus "QUIT" keystrokes carrying over from the game, by
  252.                                                 ;using the menu_frame counter at the end of this FOR loop.
  253.             FLAG_PAUSE = 0
  254.             FlushKeys
  255.         End If
  256.         If KeyDown(KEY_DEBUG)                ;if the user presses the "DEBUG" button on the keyboard, then..
  257.             FlushKeys
  258.             FLAG_DEBUG = 1                        ;this is all exactly the same as "FIRE" above, but now FLAG_DEBUG is set to 1.
  259.             FLAG_GAMESTARTER = 1                ;later on, you'll see that we use this to turn on, or off, some overlayed displays in the game loop!
  260.             hypercount = 102
  261.             FLAG_PAUSE = 0
  262.             game_loop()
  263.             menu_ship_ver = SCREEN_HEIGHT+1
  264.             menu_frame = 1
  265.             menu_start_stat = 0
  266.             menu_accept_quit = 0
  267.             FLAG_PAUSE = 0
  268.             FlushKeys
  269.         End If            
  270.         If KeyDown(KEY_SAVESCREEN)            ;if the user presses the "SAVESCREEN" button on the keyboard, then..
  271.             FlushKeys
  272.             FLAG_SAVESCREEN = 1                    ;just sets FLAG_SAVESCREEN to 1. You'll see this used in the next function.
  273.         End If
  274.         If menu_ship_ver > (-50 - ImageHeight(menu_ship1)) ;if the bottom of the (largest) ship picture gets to 50 pixels above the top of the screen
  275.             Select menu_ship_type    ;A SELECT..CASE statement is like an IF statement, but only performs 1 check, i.e.: "What is the value of I?"
  276.                 Case 1    ;if "menu_ship_type" is 1 then..
  277.                     menu_ship_ver = menu_ship_ver - .3 ;how fast menuship1 moves up the screen
  278.                 Case 2    ;if "menu_ship_type" is 1 then..
  279.                     menu_ship_ver = menu_ship_ver - .8 ;how fast menuship2 moves up the screen
  280.             End Select
  281.         Else
  282.             menu_ship_ver = SCREEN_HEIGHT+1    ;reset the vertical position so that the top of the ship is at the bottom of the screen
  283.             menu_ship_hor = Rnd(0,SCREEN_WIDTH-ImageWidth(menu_ship1)) ;create a random horizontal position
  284.             menu_ship_type = Int(Rnd(1,2)) ;randomly choose between values 1 or 2
  285.         End If
  286.         menu_frame = menu_frame + 1        ;increase the value of "menu_frame" by 1
  287.         If menu_frame = 25 Then            ;if the value of "menu_frame" gets to 25 then reset it to 1
  288.             menu_frame = 1
  289.             menu_accept_quit = 1            ;now we've turned the user's ability to press the "QUIT" button back on (see the IF statement in the KeyDown(KEY_QUIT) statement above!
  290.             If menu_start_stat = 1 Then    ;this bit just switches the value of "menu_start_stat" between 1 and 0, i.e. :If it's 1, then make it 0, if it's 0, then make it 1 etc.
  291.                 menu_start_stat = 0        ;this will be used in the next function to flash the "PRESS FIRE TO START" caption on and off!
  292.             Else
  293.                 menu_start_stat = 1
  294.             End If
  295.         End If
  296.     Next
  297.     menu_draw_update() ;call the function "menu_draw_update" which draws all these new things on the screen
  298. End Function
  299.  
  300. ;"menu_draw_update()" just draws things on your monitor, using values set and altered in the last function (menu_loop_update).
  301. Function menu_draw_update()
  302.     SetBuffer BackBuffer()    ;draw all of the following to the backbuffer() which is an area video memory which is not shown on screen.
  303.                             ;the idea is that you draw everything here, then SHOW it to the user when the full picture is complete.
  304.                             
  305.     ClsColor 0,0,0        ;changes the CLearScreen colour to black (0,0,0)
  306.                         ;Color commands use the 3 parameters as RED value, GREEN value, BLUE value
  307.                         ;which is how pixel colours are made up on the monitor. If you're familiar with
  308.                         ;any PC Paint Packages, you'll probably be quite familiar with this.
  309.     Cls                    ;CLears the Screen
  310.     
  311.     ;this next section draws all of the pictures on to the backbuffer() at the specified coordinates.
  312.     ;notice that the pictures are drawn in sequence, with the backmost things drawn first and the foremost things drawn last
  313.     ;kind of like making a collage!
  314.     DrawImage menu_logo,(SCREEN_WIDTH/2)-(ImageWidth(menu_logo)/2),0    ;this draws the menu_logo image at "x","y"
  315.                         ;I've used EQUATIONS to make up x and y for all the images in this project, so that when you change
  316.                         ;the resolution values (back at the beginning of the code) everything still appears at the correct position
  317.                         ;on the screen. If you know what resolution you'll be working at, then you can quite happily put x and y as
  318.                         ;ordinary numbers in here.
  319.                         ;For example, at 800*600, the menu_logo image will be drawn at:
  320.                         ;SCREEN_WIDTH = 800
  321.                         ;800/2 = 400
  322.                         ;ImageWidth(menu_logo) is the width (in pixels) of this particular image (which is 547 pixels)
  323.                         ;547/2 = 273.5
  324.                         ;(800 - 273.5 = 126.5)
  325.                         ;So, menu_logo would be drawn at 127,0 (because Blitz requires whole number coordinates, it will automatically
  326.                         ;round up 126.5 to be 127.)
  327.     DrawImage menu_guildhall,(SCREEN_WIDTH/2)-(ImageWidth(menu_guildhall)/2),5
  328.     DrawImage menu_credit,(SCREEN_WIDTH/2)-(ImageWidth(menu_credit)/2),200
  329.     DrawImage menu_quit,(SCREEN_WIDTH/2)-(ImageWidth(menu_quit)/2),SCREEN_HEIGHT-75
  330.     DrawImage menu_thanks,(SCREEN_WIDTH/2)-(ImageWidth(menu_thanks)/2),SCREEN_HEIGHT-15
  331.  
  332.     ;depending on the value set earlier in "menu_loop_update()" this draws one of the two ships at the relevant coordinates on-screen
  333.     ;menu_ship_hor is the x position, and is set once per "scroll up the screen" in menu_loop_update().
  334.     ;menu_ship_ver is the y position, which is repeatedly changed in menu_loop_update() to scroll the ships up the screen!
  335.     Select menu_ship_type
  336.         Case 1
  337.             DrawImage menu_ship1,menu_ship_hor,menu_ship_ver
  338.         Case 2
  339.             DrawImage menu_ship2,menu_ship_hor,menu_ship_ver
  340.     End Select
  341.     
  342.     ;Remember before, I was saying that "menu_frame" would be used to flash the "START GAME" caption on and off?
  343.     ;when "menu_frame" got to 25, the variable "menu_start_stat" was flipped between 1 or 0
  344.     If menu_start_stat = 1 Then
  345.         ;if the variable "menu_start_stat" = 1 then draw the caption. If it isn't, ignore drawing the caption.
  346.         ;On and off, on and off. Simple as that! This technique will be used again later for the PAUSE and GAME_OVER captions!
  347.         DrawImage menu_start,(SCREEN_WIDTH/2)-(ImageWidth(menu_start)/2),(SCREEN_HEIGHT/2)+(ImageHeight(menu_start)*4)
  348.     End If
  349.  
  350.     ;Remember when we checked to see if the user had pressed the "SAVESCREEN" button, earlier?
  351.     ;if they did, we set FLAG_SAVESCREEN to 1. Now this is where that takes effect..
  352.     If FLAG_SAVESCREEN=1 Then
  353.         SaveBuffer (BackBuffer(),"CRMenuScreen.bmp")
  354.             ;the SaveBuffer command outputs the contents of the named buffer (in this case "BackBuffer()") to the named file, in a BMP format.
  355.         FLAG_SAVESCREEN = 0
  356.             ;after we've saved the screen, we reset the FLAG to 0, so that when we come back for the next "menu_draw_update", it won't save
  357.             ;another picture. (i.e.: it only saves 1 picture for each keypress of the "SAVESCREEN" button!)
  358.             ;This is useful for getting working screenshots of your project to impress your mates!! :)
  359.     End If 
  360.     Flip    ;finally, FLIP everything on the backbuffer() and show it on the frontbuffer(), i.e.: your monitor!!
  361. End Function
  362.  
  363. ;this function keeps the game loop going.. It starts playing tunes and sets a couple of variables. 
  364. ;Then it goes into a never ending loop which carries out a sequence of checks and function calls, until such time as we want to stop it!
  365. Function game_loop()
  366.     FLAG_GAMEON = 1 ;tells the program that the game is running.
  367.     game_initialise()     ;calls a function called "game_initialise()" (which is next in the code) which
  368.                         ;just gives the player full energy and a score of 0 etc..)
  369.     Repeat        ;as with the menu, we want to cycle though the process of updating/drawing forever, until such time as the game has ended.
  370.         If FLAG_GAMEON = 1 Then        ;.. so, if FLAG_GAMEON is 1, then "do" the following.
  371.             game_loop_update()                                ;call the game_loop_update() function
  372.         Else
  373.             FlushKeys                ;if FLAG_GAMEON isn't 1, then instead of ENDing the program (as we did from the menu), this time
  374.             Exit                    ;we EXIT the function, which effectively takes us back to the line after "game_loop()" was originally
  375.                                     ;called, back in "menu_loop_update()"
  376.         End If
  377.     Forever
  378. End Function
  379.  
  380. ;As described a minute ago, this function sets up the game variables as they should be
  381. ;at the start of every game, i.e.: Player Shields are full, the score is 0 etc..
  382. Function game_initialise()
  383.     PLAYER_SCORE = 0
  384.     PLAYER_TIME = 0
  385.     PLAYER_ANGLE = 0
  386.     PLAYER_SPEED = 0
  387.     PLAYER_SHIELD = 192            ;the width of the game_level image is 192. Rather than working out a percentage of 100, it's much
  388.     PLAYER_BOOSTERS = 192        ;easier to use the width of the image on such BAR type displays.
  389.     PLAYER_CLOAK = 192            
  390.     PLAYER_JUMPS = 5
  391.     game_player_randomize()            ;calls a function that randomizes a player's position on the map
  392.     game_stars_randomize()            ;calls a function that randomizes the star positions
  393.  
  394.     ;this next bit is the first time you'll have seen a TYPE cycle.
  395.     ;Just like a normal "For i = 0 to 20" loop, this goes through each Version of a type
  396.     ;and set's it's properties. (i.e.: That FISH type has a SCALES property. Here we tell it that this particular Fish's Scales are GOLD!)
  397.     For icon.icons = Each icons
  398.         icon\x = Rnd(0,GAME_AREA_X)        ;for each of the 4 icons on the play area at any one point, we need a random x and y position.
  399.         icon\y = Rnd(0,GAME_AREA_Y)
  400.     Next
  401. End Function
  402.  
  403. ;once again, like it's menu equivalent, "game_loop_update()" is a function which analyses player input, working out all the new
  404. ;coordinate positions and anything else which needs deciding before updating the screen display.
  405. Function game_loop_update()
  406.     frames = WaitTimer(timer)
  407.     For i = 1 To frames
  408.         If KeyDown(KEY_PAUSE)                                    ;checks to see if the user has pressed the "PAUSE" key
  409.             FlushKeys
  410.             If game_accept_pause = 1                            ;the "game_accept_pause" variable is used in the same way as "menu_accept_quit" earlier.
  411.                                                                 ;because we're using SCANCODES, the program will register a number of qualifying cases where
  412.                                                                 ;when this check is performed, the key is still held down (at 50 frames per second, if the user
  413.                                                                 ;held down the key for half a second, the KEYDOWN function would fire around 25 times!)
  414.                                                                 
  415.                 If FLAG_PAUSE = 0 Then                            ;If FLAG_PAUSE is 0 then..
  416.                     FLAG_PAUSE = 1                                ;make FLAG_PAUSE = 1
  417.                     game_accept_pause = 0                        ;don't accept any more "PAUSE" button presses until "game_accept_pause" is set back to 1
  418.                     game_pause_frame = 1                        ;make "game_pause_frame" = 1 which, similarly to "menu_frame" earlier will enable the flashing of "PAUSED".
  419.                 Else
  420.                     FLAG_PAUSE = 0                                ;If FLAG_PAUSE isn't 0 (the game was paused) then..
  421.                     game_accept_pause = 0                        ;do exactly the same, but set FLAG_PAUSE to 0.
  422.                     game_pause_frame = 1
  423.                 End If
  424.             End If
  425.         End If
  426.         If KeyDown(KEY_SAVESCREEN)        ;If the "SCREENSAVE" button is pressed..
  427.             FlushKeys                    ;this functions exactly the same as in menu_loop_update()
  428.             FLAG_SAVESCREEN = 1
  429.         End If
  430.         If KeyDown(KEY_QUIT)        ;If the "QUIT" button is pressed..
  431.             FlushKeys
  432.             hypercount = 0
  433.             cloakon = 0
  434.             FLAG_GAMEON=0             ;set FLAG_GAMEON to equal 0. Back in the "game_loop()" function, this will cause the code to jump back to the menu.
  435.         End If
  436.  
  437.         If FLAG_PAUSE = 0 Then                            ;this is really easy! If the game is paused then *don't* do any of the following code. No values will change,
  438.                                                         ;hence nothing will move on the screen when it comes to updating it later! :)
  439.                                                         
  440.                 If KeyDown(KEY_HYPER)                    ;if the "HYPER" key is pressed then..
  441.                     If PLAYER_JUMPS > 0 Then
  442.                         If hypercount = 0 Then                ;(if "hypercount" is 0, then we're not already in the middle of a HyperJump, so let's set things off!)
  443.                             hypercount = 1                        ;by setting "hypercount" to 1, we'll set off a chain of events later on..
  444.                             PLAYER_JUMPS = PLAYER_JUMPS - 1        ;subtract the number of Jumps a player has left by 1
  445.                             If PLAYER_JUMPS <= 0 Then            ;if the number of jumps left is 0 or less, then the above subtraction will make it "-1", so..
  446.                                 PLAYER_JUMPS = 0                ;put it back to 0.
  447.                             End If
  448.                         End If
  449.                     End If
  450.                     FlushKeys
  451.                 End If
  452.                 If hypercount = 0 Then                        ;as long as we're not in the middle of a hyperjump, do the following..
  453.                 
  454.                     If KeyDown(KEY_CLOAK)            ;if the CLOAK key is pressed then
  455.                     
  456.                         If PLAYER_CLOAK > 2 Then        ;if the player has enough (2 points of) PLAYER_CLOAK left, then..
  457.                             cloakon = cloakon + 1                                    ;the cloakon value is incremented so that later on, we can do the flickering effect
  458.                             PLAYER_CLOAK = PLAYER_CLOAK - INCR_CLOAK_DOWN            ;subtract some PLAYER_CLOAK ability at a rate of "INCR_CLOAK_DOWN"
  459.                             
  460.                         Else                            ;if the player doesn't have enough PLAYER_CLOAK left then
  461.                             cloakon = 0                        ;reset the "cloakon" value to 0
  462.                             PLAYER_CLOAK = 0                ;Keep the PLAYER_CLOAK value at 0, so that it doesn't build up...
  463.                         End If
  464.                         FlushKeys
  465.                     Else                            ;if the CLOAK key isn't pressed then
  466.                         cloakon = 0                            ;reset the "cloakon" value to 0
  467.                         If PLAYER_CLOAK < 192                                ;if the player has less than the top value (192 points) of PLAYER_CLOAK then..
  468.                             PLAYER_CLOAK = PLAYER_CLOAK + INCR_CLOAK_UP            ;Slowly build up the PLAYER_CLOAK value.
  469.                         Else
  470.                             PLAYER_CLOAK = 192                                ;otherwise cap the PLAYER_CLOAK value at 192 points.
  471.                         End If
  472.                         FlushKeys
  473.                     End If
  474.                     If KeyDown(KEY_BOOST)                            ;the BOOST key works in exactly the same way as the CLOAK key
  475.                         If PLAYER_BOOSTERS > 2 Then
  476.                             If PLAYER_SPEED < (SPEED_MAX*3) Then
  477.                                 PLAYER_SPEED = PLAYER_SPEED + (INCR_SPEED * 3)
  478.                             End If
  479.                             PLAYER_BOOSTERS = PLAYER_BOOSTERS - INCR_BOOSTERS_DOWN
  480.                         Else
  481.                             PLAYER_BOOSTERS = 0
  482.                         End If
  483.                         FlushKeys
  484.                     Else
  485.                         If PLAYER_BOOSTERS < 192
  486.                             PLAYER_BOOSTERS = PLAYER_BOOSTERS + INCR_BOOSTERS_UP
  487.                         Else
  488.                             PLAYER_BOOSTERS = 192
  489.                         End If
  490.                         FlushKeys
  491.                     End If
  492.                     If KeyDown(KEY_FIRE) Then                    ;if the "FIRE" key is pressed, then..
  493.                         If bulletlimiter = 0 Then                    ;the "bulletlimiter" value works in exactly the same way as "game_accept_pause" earlier
  494.                                                                     ;in that we don't want too many bullets spraying out of the player, due to SCANCODE/framerate issues
  495.                             bulletlimiter = 1                        ;so we set the "bulletlimiter value to 1, so that until we say so (a bit later) no more "FIRE" keypresses
  496.                                                                     ;will trigger.
  497.                                                                     
  498.                             createbullet(PLAYER_X,PLAYER_Y,PLAYER_ANGLE,PLAYER_SPEED,1)        ;however, assuming we've got a successful "FIRE" event, let's create some bullets
  499.                                                                                             ;on the screen by calling the "createbullet()" function.. This is pretty cool, so
  500.                                                                                             ;see the function itself later on for explainations!
  501.                         End If
  502.                         FlushKeys
  503.                     End If
  504.                     If KeyDown(KEY_CLOCKWISE)                            ;if "CLOCKWISE" key is pressed then..
  505.                         PLAYER_ANGLE = PLAYER_ANGLE + INCR_ROTATE            ;Add "INCR_ROTATE" degrees to the current PLAYER_ANGLE
  506.                         FlushKeys
  507.                         If PLAYER_ANGLE >= 360 Then                            ;if the PLAYER_ANGLE is 360, then reset it to 0.
  508.                             PLAYER_ANGLE = PLAYER_ANGLE - 360
  509.                         End If
  510.                     End If
  511.                     If KeyDown(KEY_ANTICWISE)                            ;exactly the same, but Subtract "INCR_ROTATE" from the player angle and
  512.                         PLAYER_ANGLE = PLAYER_ANGLE - INCR_ROTATE        ;reset it to (for example) 355, if the angle is -5.
  513.                         FlushKeys
  514.                         If PLAYER_ANGLE < 0 Then
  515.                             PLAYER_ANGLE = PLAYER_ANGLE + 360
  516.                         End If
  517.                     End If
  518.                     If KeyDown(KEY_SPEEDUP) Then                        ;if the "SPEEDUP" key is pressed.
  519.                         If PLAYER_SPEED < SPEED_MAX                            ;as long as the player speed is less than the maximum speed (SPEED_MAX), then
  520.                             PLAYER_SPEED = PLAYER_SPEED + INCR_SPEED        ;Add "INCR_SPEED" to the player's speed value
  521.                             FlushKeys
  522.                         Else
  523.                             PLAYER_SPEED = PLAYER_SPEED - INCR_SLOW            ;if the PLAYER_SPEED is not less than the maximum speed then take "INCR_SLOW" off of it!
  524.                             FlushKeys
  525.                         End If
  526.                     Else                                                ;if the key isn't being pressed, then..
  527.                         If PLAYER_SPEED > 0 Then                            ;as long as the player speed is greater than 0, then take "INCR_SLOW" off the current value
  528.                             PLAYER_SPEED = PLAYER_SPEED - INCR_SLOW            ;(this is an easy "No power" decelaration for the space ship)
  529.                         End If
  530.                         FlushKeys
  531.                     End If
  532.                     If KeyDown(KEY_SPEEDDOWN)                            ;exactly the same thing, but with the ship's thrusters in reverse! :)
  533.                         If PLAYER_SPEED > SPEED_MIN
  534.                             PLAYER_SPEED = PLAYER_SPEED - INCR_SPEED
  535.                             FlushKeys
  536.                         Else
  537.                             PLAYER_SPEED = SPEED_MIN
  538.                             FlushKeys
  539.                         End If
  540.                     Else
  541.                         If PLAYER_SPEED < 0 Then
  542.                             PLAYER_SPEED = PLAYER_SPEED + INCR_SLOW
  543.                         End If
  544.                     End If
  545.                 End If    ;end of the "If we're not in the middle of a hyperjump" IF statement
  546.                 
  547.                 ;this next peice of code updates the player position on the map, relative to it's Speed and Angle and it's last position
  548.                 PLAYER_X = PLAYER_X + (PLAYER_SPEED*(Sin(PLAYER_ANGLE)/2))
  549.                 PLAYER_Y = PLAYER_Y - (PLAYER_SPEED*(Cos(PLAYER_ANGLE)/2))
  550.                 If PLAYER_X < 0 Then                        ;if the PLAYER_X value is less than 0, then wrap your position around the map
  551.                     PLAYER_X = (PLAYER_X + GAME_AREA_X)        ;by adding the GAME_AREA_X value to the negative value, i.e.: -5 becomes 19995 on a 20000 X pixel map.
  552.                 End If
  553.                 If PLAYER_X > GAME_AREA_X Then                ;the same in reverse, i.e. 20004 becomes 4 on the same map.
  554.                     PLAYER_X = (PLAYER_X - GAME_AREA_X)
  555.                 End If
  556.                 If PLAYER_Y < 0 Then                        ;and now the same for the Y direction
  557.                     PLAYER_Y = (PLAYER_Y + GAME_AREA_Y)
  558.                 End If
  559.                 If PLAYER_Y > GAME_AREA_Y Then
  560.                     PLAYER_Y = (PLAYER_Y - GAME_AREA_Y)
  561.                 End If
  562.     
  563.             For icon.icons=Each icons                ;the "icons" don't move from their randomly set x,y position, so all we need to do for them is
  564.                 icon\frame = icon\frame+.5            ;update their animation frame number. There are 6 frames, and we're incrementing at 0.5 frames per update.
  565.                 If Int(icon\frame) = 6 Then            ;in real terms, this means we'll be updating the frame number every 2 updates.
  566.                     icon\frame = 0                    ;Because the icon animations are simple 0 to 5 cycling animations, when the frame number reaches 6, we flip it back to 0
  567.                 End If                                ;to start the sequence again.
  568.             Next
  569.             
  570.             ;this next bit of code creates the "simple but effective" Hyperjump event, based entirely on the value of "hypercount" being set to 1, earlier in the code.
  571.             If hypercount > 0 Then
  572.                 If (hypercount/2 = Int(hypercount/2)) Then    ;this line says "If the value of 'hypercount' is an EVEN number"
  573.                                                             ;because 5 (an odd number) would be 2.5 when devided by 2, but conversion to an INTeger gives 3.
  574.                                                             ;2.5 does NOT equal 3!
  575.                     ;all of this simply rotates the HyperJump ships in different offset directions
  576.                     ;the only difference is, we're not bothering with degrees here, just animation frame numbers, i.e.: 355 degrees is frame 71 (i.e.: 355/5 degree increment)
  577.                     frame1 = frame1 + 3
  578.                     frame2 = frame2 - 3
  579.                     frame3 = frame1 + 9
  580.                     frame4 = frame2 - 9
  581.                     frame5 = frame1 + 36
  582.                     frame6 = frame2 - 36
  583.                     frame7 = frame1 + 54
  584.                     frame8 = frame2 - 54
  585.                     If frame1 >=72 Then
  586.                         frame1 = frame1-72
  587.                     End If
  588.                     If frame1 < 0 Then
  589.                         frame1 = frame1+72
  590.                     End If
  591.                     If frame2 >=72 Then
  592.                         frame2 = frame2-72
  593.                     End If
  594.                     If frame2 < 0 Then
  595.                         frame2 = frame2+72
  596.                     End If
  597.                     If frame3 >=72 Then
  598.                         frame3 = frame3-72
  599.                     End If
  600.                     If frame3 < 0 Then
  601.                         frame3 = frame3+72
  602.                     End If
  603.                     If frame4 >=72 Then
  604.                         frame4 = frame4-72
  605.                     End If
  606.                     If frame4 < 0 Then
  607.                         frame4 = frame4+72
  608.                     End If
  609.                     If frame5 >=72 Then
  610.                         frame5 = frame5-72
  611.                     End If
  612.                     If frame5 < 0 Then
  613.                         frame5 = frame5+72
  614.                     End If
  615.                     If frame6 >=72 Then
  616.                         frame6 = frame6-72
  617.                     End If
  618.                     If frame6 < 0 Then
  619.                         frame6 = frame6+72
  620.                     End If
  621.                     If frame7 >=72 Then
  622.                         frame7 = frame7-72
  623.                     End If
  624.                     If frame7 < 0 Then
  625.                         frame7 = frame7+72
  626.                     End If
  627.                     If frame8 >=72 Then
  628.                         frame8 = frame8-72
  629.                     End If
  630.                     If frame8 < 0 Then
  631.                         frame8 = frame8+72
  632.                     End If
  633.                 End If    ;end of the "if hypercount is EVEN" IF statement
  634.                 
  635.                 ;this bit increases the value of "hypercount" until it reaches 200
  636.                 hypercount = hypercount + 1
  637.                 If hypercount > 0 And hypercount <= 102 Then    ;between 0 and 102, the player speed increases
  638.                     PLAYER_SPEED = PLAYER_SPEED + 2
  639.                 ElseIf hypercount > 102 And hypercount < 200 Then    ;between 102 and 200, the player speed decreases (but only if FLAG_GAMESTARTER is 0)
  640.                     If FLAG_GAMESTARTER = 0 Then                    ;this is because when the game starts, the player speed is 0, but we've faked being in
  641.                         PLAYER_SPEED = PLAYER_SPEED - 2                ;the middle of a hyperjump. Without this FLAG, the player ship would start each game
  642.                     End If                                            ;travelling at about -90 speed backwards, which would just be weird! :)
  643.                 End If
  644.                 If hypercount = 100 Then
  645.                     game_stars_randomize()    ;half way through the Hyperjump sequence, the "game_stars_randomize()" function is called, which changes all the star positions    
  646.                                             ;and depths, to give the impression we've moved to a completely different part of space
  647.                 End If
  648.                 If hypercount/10 = Int(hypercount/10) Then
  649.                     game_player_randomize()        ;every 10 updates, the function "game_player_randomize()" is called. This randomly jumps the player around the map
  650.                                                 ;and confuses the hell out of the bad guys! (well it will by next month's tutorial!!) ;))
  651.                 End If
  652.                 If hypercount = 200 Then        ;if the "hypercount" variable reaches 200, then stop the sequence and reset the value back to 0
  653.                     hypercount = 0
  654.                     FLAG_GAMESTARTER = 0        ;also, when the game first starts we were in the middle of a hyperjump. Resetting this FLAG back to 0 means that
  655.                                                 ;the next hyperjump sequence will decrease the speed after "hypercount" gets to 103
  656.                 End If
  657.             Else                            ;if we're not in the middle of a hyperjump event, then:
  658.                 frame1=game_player_frame-1    ;this bit is just for the DEBUG mode. It was designed to check that 360 degrees became 0 degrees and vice versa correctly
  659.                 frame2=game_player_frame+1
  660.                 If frame1 < 0 Then
  661.                     frame1 = frame1 + 72
  662.                 End If
  663.                 If frame2 >= 72 Then
  664.                     frame2 = frame2 - 72
  665.                 End If
  666.             End If    ;end of the "Are we in the middle of a Hyperjump" IF statement
  667.             
  668.             ;the parralex stars move relative to the player and is just the same "menustars" number of stars
  669.             ;scrolled at various speeds, wrapping around the screen.
  670.             ;it's a fairly cheap, but effective way of creating a nice illusion of speed!
  671.             If starson=1 Then                ;if, at the beginning of the program, you set "starson" to 0, the stars will disappear.
  672.                                             ;the game would also feel pretty bloody wierd.. hold on.. yep.. Absolutely mad! Try it! :)
  673.                 For star.stars=Each stars
  674.                     ;the following two lines move each version of the "stars" Type an x and y distance relative to the player's speed and angle
  675.                     ;with a devision relative to the depth of the star to make the smallest stars move slower than the biggest
  676.                     ;thus we have our parallex effect.
  677.                     
  678.                     ;it might be of interest to know that these two lines were based on the OLDSKOOL demo which comes with Blitz Basic
  679.                     ;and was the starting point for the whole CELESTIAL RIFT game concept! Thanks a lot, Mr Mikkel L°kke!! :)
  680.                     star\y=(star\y+PLAYER_SPEED*(Cos(360-PLAYER_ANGLE)/(6-star\depth+1)))
  681.                     star\x=(star\x+PLAYER_SPEED*(Sin(360-PLAYER_ANGLE)/(6-star\depth+1)))
  682.                     ;the maximum pixel width of for the biggest star image is 5 pixels
  683.                     ;the following IF statements wrap the stars around the screen border when they reach the extremities
  684.                     If star\x < -5 Then
  685.                         star\x = star\x + (SCREEN_WIDTH + 5)
  686.                     End If
  687.                     If star\x > SCREEN_WIDTH Then
  688.                         star\x = star\x - (SCREEN_WIDTH + 5)
  689.                     End If
  690.                     If star\y <= -5 Then
  691.                         star\y = star\y + (SCREEN_HEIGHT + 5)
  692.                     End If
  693.                     If star\y >= SCREEN_HEIGHT
  694.                         star\y = star\y - (SCREEN_HEIGHT + 5)
  695.                     End If
  696.                 Next
  697.             End If    ;end of the "are the stars going to be shown" IF statement
  698.  
  699.             ;the following lines calculate all the bullet positions, relative to their originally set SPEED and ANGLE from the "createbullet" function.
  700.             For i = 0 To bulletnum-1
  701.                 If bullets(i,4) > 0 Then        ;if the bullet isn't 0, i.e.: it's "on"
  702.                 
  703.                     bullets(i,0) = bullets(i,0) + (bullets(i,3)*(Sin(bullets(i,2))/2))    ;bullet x position = bullet x position + (bullet speed * (SIN (bullet angle) / 2)
  704.                     bullets(i,1) = bullets(i,1) - (bullets(i,3)*(Cos(bullets(i,2))/2))    ;bullet y position = bullet y position + (bullet speed * (COS (bullet angle) / 2)
  705.                                 ;try turning these last two lines off for a crazy pulsing effect of bullets that you can use
  706.                                 ;to surround the player, creating a kind of enemy-deadly minefield.. Madness! :)
  707.                     
  708.                     bullets(i,5) = bullets(i,5) + 1        ;increases the animation frame of the bullet
  709.                     If bullets(i,5) = 6 Then    ;if the animation frame is 6 then flip it back to 0 (the bullet animation runs frames 0, 1, 2, 3, 4, 5, 0, 1, 2 ... etc)
  710.                         bullets(i,5) = 0
  711.                     End If
  712.                     
  713.                     ;as with the player and enemies, this next bit wraps the bullets around the map extremities
  714.                     If bullets(i,0) < 0 Then
  715.                         bullets(i,0) = (bullets(i,0) + GAME_AREA_X)
  716.                     End If
  717.                     If bullets(i,0) > GAME_AREA_X Then
  718.                         bullets(i,0) = (bullets(i,0) - GAME_AREA_X)
  719.                     End If
  720.                     If bullets(i,1) < 0 Then
  721.                         bullets(i,1) = (bullets(i,1) + GAME_AREA_X)
  722.                     End If
  723.                     If bullets(i,1) > GAME_AREA_Y Then
  724.                         bullets(i,1) = (bullets(i,1) - GAME_AREA_Y)
  725.                     End If
  726.                     
  727.                     ;like the enemies "distance from player", this bit checks if a bullet has gone a certain distance from it's origin
  728.                     temp_x1# = bullets(i,0) - bullets(i,6) ;origin x on the right
  729.                     temp_y1# = bullets(i,1) - bullets(i,7) ;origin y on the top
  730.                     temp_x2# = bullets(i,6) - bullets(i,0) ;origin x on the left
  731.                     temp_y2# = bullets(i,7) - bullets(i,1) ;origin y on the bottom
  732.  
  733.                     ;wraps distances around the map extremities
  734.                     If temp_x1# < 0 Then
  735.                         temp_x1# = temp_x1# + GAME_AREA_X
  736.                     End If
  737.                     If temp_x1# > GAME_AREA_X Then
  738.                         temp_x1# = temp_x1# - GAME_AREA_X
  739.                     End If
  740.                     If temp_y1# < 0 Then
  741.                         temp_y1# = temp_y1# + GAME_AREA_Y
  742.                     End If
  743.                     If temp_x1# > GAME_AREA_X Then
  744.                         temp_y1# = temp_y1# - GAME_AREA_Y
  745.                     End If
  746.                     If temp_x2# < 0 Then
  747.                         temp_x2# = temp_x2# + GAME_AREA_X
  748.                     End If
  749.                     If temp_x2# > GAME_AREA_X Then
  750.                         temp_x2# = temp_x2# - GAME_AREA_X
  751.                     End If
  752.                     If temp_y2# < 0 Then
  753.                         temp_y2# = temp_y2# + GAME_AREA_Y
  754.                     End If
  755.                     If temp_x2# > GAME_AREA_X Then
  756.                         temp_y2# = temp_y2# - GAME_AREA_Y
  757.                     End If
  758.                     
  759.                     ;calculates the shortest distance
  760.                     If Abs(temp_x1#) < Abs(temp_x2#) Then
  761.                         temp_x# = Abs(temp_x1#)
  762.                     Else
  763.                         temp_x# = Abs(temp_x2#)
  764.                     End If
  765.                     If Abs(temp_y1#) < Abs(temp_y2#) Then
  766.                         temp_y# = Abs(temp_y1#)
  767.                     Else
  768.                         temp_y# = Abs(temp_y2#)
  769.                     End If
  770.                     
  771.                     ;back to PYTHAGORAS to work out the "As the crow flies" distance from the bullet's original starting point
  772.                     temp_x# = Abs(temp_x# / 200)
  773.                     temp_y# = Abs(temp_y# / 200)
  774.                     temp_hyp# = (temp_x#*temp_x#) + (temp_y#*temp_y#)
  775.                     temp_hyp# = Sqr(temp_hyp#)
  776.  
  777.                     ;if the bullet has travelled "5" units from it's starting point, then..
  778.                     If temp_hyp# > 5 Then
  779.                         bullets(i,4) = 0    ;turn the bullet off
  780.                     End If
  781.                 End If
  782.             Next    ;end of bullet coordinate repositioning loop
  783.             
  784.             ;this is the player's bullet limiting code, basically only allowing the player to fire every 10 frames (otherwise it looks more like the player is spraying water!!)
  785.             If bulletlimiter > 0 Then
  786.                 bulletlimiter = bulletlimiter + 1
  787.                 If bulletlimiter = 10 Then ;value essentially sets the fire-rate (the lower the number, the faster the fire rate!)
  788.                     bulletlimiter = 0
  789.                 End If
  790.             End If
  791.             
  792.             PLAYER_SCORE = PLAYER_SCORE + 1        ;if the game is in progress, then increase the PLAYER_SCORE by 1 every screen update
  793.                                                     ;this acts as a kind of survival bonus for the more defensive player
  794.                 If PLAYER_SCORE >= HI_SCORE Then
  795.                     HI_SCORE = PLAYER_SCORE
  796.                 End If
  797.             
  798.         End If ;end of "IF FLAG_PAUSE = 0" IF Statement
  799.         
  800.         ;this flashes the "PAUSED" caption on and off when needs be!
  801.         game_pause_frame = game_pause_frame + 1
  802.         If game_pause_frame = 25 Then
  803.             game_pause_frame = 1
  804.             game_accept_pause = 1
  805.             If game_pause_stat = 1 Then
  806.                 game_pause_stat = 0
  807.             Else
  808.                 game_pause_stat = 1
  809.             End If
  810.         End If
  811.  
  812.     Next    ;end of the "for i = 1 to frames" FOR loop
  813.     
  814.     game_draw_update()    ;finally, draw all the pictures on the screen, based on their (possibly) new positions.
  815. End Function
  816.  
  817. ;this function draws the game graphics in their freshly calculated positions
  818. Function game_draw_update()
  819.     SetBuffer BackBuffer()    ;draw all of the following to the backbuffer
  820.     ClsColor 0,0,0            ;changes the CLearScreen colour to black (0,0,0)
  821.     Cls
  822.     If starson=1 Then        ;draw all of the stars using their correct pictures, at the correct x and y positions
  823.         For star.stars=Each stars ;(for each star in type 'stars' do the following..)
  824.             DrawImage game_stars(star\depth),star\x,star\y    ;using the depth property of "stars" as the Array position
  825.         Next
  826.     End If
  827.     
  828.         ;this FOR Type loop draws all the versions of "icons" at their screen-position - relative to the PLAYER coordinates
  829.         ;in the current animation frame. It also checks for the non-transparent areas of the ICON image touching the non-
  830.         ;transparent areas of the PLAYER image and updates the PLAYER's relavent energy-level values.
  831.         For icon.icons=Each icons
  832.         
  833.             ;this line draws the relavant icon image at coordinates "x" and "y" on (or off) the screen
  834.             ;the correct icon image is chosen using the "icons"'s style as it's array position
  835.             ;the x and y coordinates are worked out by subtracting the PLAYER's current position from the "icons"'s current position
  836.             ;notice that we're using the same style of "SCREEN_WIDTH\2 - Half the ImageWidth of the Image" idea from the
  837.             ;"menu_draw_update()" code?
  838.             DrawImage game_icons(icon\style), (((SCREEN_WIDTH/2)-ImageWidth(game_icons(icon\style))/2) - (PLAYER_X - icon\x)), (((SCREEN_HEIGHT/2)-ImageWidth(game_icons(icon\style))/2) - (PLAYER_Y - icon\y)),Int(icon\frame)
  839.  
  840.         Next    ;end of the "icons" FOR loop
  841.  
  842.         ;now we'll do the same for all the bullets on (or off) the screen    
  843.         For i = 0 To bulletnum-1    ;this cycles though the array from position 1 to the final bullet number in the array..
  844.                                     ;we use "bulletnum - 1" because there are (for example) 600 possible bullets that are stored
  845.                                     ;in an array as 0, 1, 2, 3 ... 596, 597, 598 and 599
  846.         
  847.             Select bullets(i,4)        ;whose bullet is it? remember when we originally DIMmed this Array, I said that 0 was off, 1 was a PLAYER bullet and 2 was an enemy bullet?
  848.                 Case 1
  849.                 
  850.                     ;if it's a player bullet then..
  851.                     ;draw this bullet at it's position, relative to the player, in it's current animation frame
  852.                     DrawImage game_bullet_player,(((SCREEN_WIDTH/2)-ImageWidth(game_bullet_player)/2) - (PLAYER_X - bullets(i,0))), (((SCREEN_HEIGHT/2)-ImageWidth(game_bullet_player)/2) - (PLAYER_Y - bullets(i,1))),bullets(i,5)
  853.             End Select
  854.         Next    ;end of the "bullet drawing/collision detecting" FOR loop
  855.  
  856.     ;this section draws the frames of "animation" for the hyperjump, or - if we're not mid hyperjump - draws the regular player frames
  857.     ;the hyperjump bits look quite complecated, but it's just x and y positions that are changing in relation to the value of "hypercount"
  858.     If hypercount > 0 And hypercount < 100 Then
  859.         If hypercount/2 = Int(hypercount/2) Then        ;if the value of "hypercount" is EVEN then..
  860.                                                         ;draw these four pictures
  861.             DrawImage game_player,(SCREEN_WIDTH/2)-ImageWidth(game_player)/2+hypercount,(SCREEN_HEIGHT/2)-ImageHeight(game_player)/2-hypercount,frame2
  862.             DrawImage game_player,(SCREEN_WIDTH/2)-ImageWidth(game_player)/2+hypercount,(SCREEN_HEIGHT/2)-ImageHeight(game_player)/2+hypercount,frame4
  863.             DrawImage game_player,(SCREEN_WIDTH/2)-ImageWidth(game_player)/2-hypercount,(SCREEN_HEIGHT/2)-ImageHeight(game_player)/2+hypercount,frame6
  864.             DrawImage game_player,(SCREEN_WIDTH/2)-ImageWidth(game_player)/2-hypercount,(SCREEN_HEIGHT/2)-ImageHeight(game_player)/2-hypercount,frame8
  865.  
  866.         Else                                            ;otherwise, if the value of "hypercount" is ODD, then..
  867.                                                         ;draw these four pictures..
  868.                                                         ;this ODD/EVEN swapping results in our "flickery" effect, but you
  869.                                                         ;can see the distinct 4 pictures if you PAUSE the game in the middle of a jump!
  870.             DrawImage game_player,(SCREEN_WIDTH/2)-ImageWidth(game_player)/2-(1.4*hypercount),(SCREEN_HEIGHT/2)-ImageHeight(game_player)/2,frame7
  871.             DrawImage game_player,(SCREEN_WIDTH/2)-ImageWidth(game_player)/2,(SCREEN_HEIGHT/2)-ImageHeight(game_player)/2+(1.4*hypercount),frame5
  872.             DrawImage game_player,(SCREEN_WIDTH/2)-ImageWidth(game_player)/2+(1.4*hypercount),(SCREEN_HEIGHT/2)-ImageHeight(game_player)/2,frame3
  873.             DrawImage game_player,(SCREEN_WIDTH/2)-ImageWidth(game_player)/2,(SCREEN_HEIGHT/2)-ImageHeight(game_player)/2-(1.4*hypercount),frame1
  874.         End If
  875.     ElseIf hypercount >= 100 And hypercount < 200 Then    ;between 0 and 100, the 8 "ships" move outwards from the middle..
  876.                                                         ;after that, they converge back to the centre, using exactly the same code, but "200 - hypercount"
  877.                                                         ;instead of "hypercount". It's a cheap effect that didn't cost me any more Paint Shop Pro time
  878.                                                         ;and it looks quite cool! :)
  879.         If hypercount/2 = Int(hypercount/2) Then
  880.             DrawImage game_player,(SCREEN_WIDTH/2)-ImageWidth(game_player)/2+(200-hypercount),(SCREEN_HEIGHT/2)-ImageHeight(game_player)/2-(200-hypercount),frame2
  881.             DrawImage game_player,(SCREEN_WIDTH/2)-ImageWidth(game_player)/2+(200-hypercount),(SCREEN_HEIGHT/2)-ImageHeight(game_player)/2+(200-hypercount),frame4
  882.             DrawImage game_player,(SCREEN_WIDTH/2)-ImageWidth(game_player)/2-(200-hypercount),(SCREEN_HEIGHT/2)-ImageHeight(game_player)/2+(200-hypercount),frame6
  883.             DrawImage game_player,(SCREEN_WIDTH/2)-ImageWidth(game_player)/2-(200-hypercount),(SCREEN_HEIGHT/2)-ImageHeight(game_player)/2-(200-hypercount),frame8
  884.         Else
  885.             DrawImage game_player,(SCREEN_WIDTH/2)-ImageWidth(game_player)/2-(1.4*(200-hypercount)),(SCREEN_HEIGHT/2)-ImageHeight(game_player)/2,frame7
  886.             DrawImage game_player,(SCREEN_WIDTH/2)-ImageWidth(game_player)/2,(SCREEN_HEIGHT/2)-ImageHeight(game_player)/2+(1.4*(200-hypercount)),frame5
  887.             DrawImage game_player,(SCREEN_WIDTH/2)-ImageWidth(game_player)/2+(1.4*(200-hypercount)),(SCREEN_HEIGHT/2)-ImageHeight(game_player)/2,frame3
  888.             DrawImage game_player,(SCREEN_WIDTH/2)-ImageWidth(game_player)/2,(SCREEN_HEIGHT/2)-ImageHeight(game_player)/2-(1.4*(200-hypercount)),frame1
  889.         End If
  890.  
  891.     Else            ;if, on the other hand, we're not mid-hyperjump, then we'll just be drawing the normal player frames..
  892.     
  893.         ;checks to see that the angle we want to draw the frame for is 0 to 71 (as 360 degrees is the same as 0 degrees!)
  894.         game_player_frame = PLAYER_ANGLE/5
  895.         If game_player_frame = 72 Then
  896.             game_player_frame = 0
  897.         End If
  898.         
  899.         If cloakon = 0 Then        ;if the "cloaking device" is off, then draw the player every screen update..
  900.             DrawImage game_player,(SCREEN_WIDTH/2)-ImageWidth(game_player)/2,(SCREEN_HEIGHT/2)-ImageHeight(game_player)/2,game_player_frame
  901.  
  902.         Else                    ;if the "cloaking device" is on, only draw the player when the "cloakon" number is EVEN..
  903.                                 ;this is our flickering effect used again..
  904.             If cloakon/2 = Int(cloakon/2) Then
  905.                 DrawImage game_player,(SCREEN_WIDTH/2)-ImageWidth(game_player)/2,(SCREEN_HEIGHT/2)-ImageHeight(game_player)/2,game_player_frame
  906.             End If
  907.         End If
  908.     End If
  909.     
  910.     ;As we said before, the foremost pictures/displayed objects are drawn last in our Video collage.
  911.     Color 0,128,0
  912.     Text SCREEN_WIDTH-210,220,"SCORE: " + PLAYER_SCORE
  913.     Text SCREEN_WIDTH-210,240,"HISCR: " + HI_SCORE
  914.     Text SCREEN_WIDTH-210,260,"BOOST: " + Int(PLAYER_BOOSTERS)
  915.     Text SCREEN_WIDTH-210,280,"CLOAK: " + Int(PLAYER_CLOAK)
  916.     Text SCREEN_WIDTH-210,300,"JUMPS: " + PLAYER_JUMPS
  917.     Line SCREEN_WIDTH-210,3,SCREEN_WIDTH-10,3
  918.     Line SCREEN_WIDTH-210,213,SCREEN_WIDTH-10,213
  919.     Line SCREEN_WIDTH-210,3,SCREEN_WIDTH-210,213
  920.     Line SCREEN_WIDTH-10,3,SCREEN_WIDTH-10,213
  921.         ;notice that by using a calculated x coordinate "SCREEN_WIDTH - value" in conjunction with a fixed
  922.         ;y coordinate, we will have the HUD images at the same distance from the top right of the screen
  923.         ;in any Graphics resolution we choose -- PLUS I've made the radar border GREEN using the color command
  924.         
  925.     Color 255,0,255
  926.     
  927.     ;this next bit of code draws the coloured dots on the radar
  928.     ;by using their game map coordinates, at a ratio to the size of the radar box graphic
  929.     For icon.icons=Each icons
  930.         ;this draws each of the icons
  931.         DrawImage game_icon_dot,((SCREEN_WIDTH-211)+icon\x/(GAME_AREA_X/200)),((9)+icon\y/(GAME_AREA_Y/200))
  932.     Next
  933.     
  934.     ;this next bit draws the player's green dot on the radar
  935.     If hypercount = 0 And cloakon=0 Then    ;if both the "hypercount" and "cloakon" features are inactive (i.e.: normal play)
  936.         ;then permanently draw the player's radar dot
  937.         DrawImage game_player_dot,((SCREEN_WIDTH-211)+PLAYER_X/(GAME_AREA_X/200)),((9)+PLAYER_Y/(GAME_AREA_Y/200))
  938.  
  939.     ElseIf hypercount = 0 And (cloakon/2 = Int(cloakon/2)) Then
  940.         ;otherwise, if the cloakon value is EVEN, draw the dot (flickery effect again)
  941.         ;but if the hypercount value isn't 0 (we're in the middle of a hyperjump) then don't do this..
  942.         ;.. consequently, even though the player's position moves on the radar map during a hyperjump,
  943.         ;and it affects the enemies, don't show this to the user!
  944.         DrawImage game_player_dot,((SCREEN_WIDTH-211)+PLAYER_X/(GAME_AREA_X/200)),((9)+PLAYER_Y/(GAME_AREA_Y/200))
  945.     End If
  946.  
  947.     ;if the game is paused (FLAG_PAUSE = 1) then draw the image when "game_pause_stat" = 1
  948.     ;this gives us our flash on-off effect as used earlier in "menu_draw_update()"
  949.     
  950.     If FLAG_PAUSE = 1 And game_pause_stat = 1 Then
  951.         DrawImage game_paused,SCREEN_WIDTH/2-ImageWidth(game_paused)/2,SCREEN_HEIGHT-((SCREEN_HEIGHT-350)/2+ImageHeight(game_paused)/2)
  952.     End If
  953.     
  954.     ;the following text will only be printed on the screen while the "FLAG_DEBUG" variable is set to 1 (F1, as I programmed it, on the main menu!)
  955.     If FLAG_DEBUG = 1 Then
  956.         ;the TEXT command writes a STRING of text onto the screen at the given coordinates in the currently set font
  957.         ;as I haven't used the LoadFont or SetFont commands, this will just be Blitz' default font.
  958.  
  959.         Color 255,255,255                                    ;just in case, set the colo(u)r of the text to WHITE (255, 255, 255)
  960.         Text 0,0,"PLAYER ANGLE = " + PLAYER_ANGLE                ;"Write the string 'PLAYER ANGLE = ' followed by the number held in PLAYER_ANGLE"
  961.         Text 0,20,"PLAYER SPEED = " + PLAYER_SPEED
  962.         Text 0,40,PLAYER_ANGLE + " / 5 = " + PLAYER_ANGLE/5
  963.         Text 0,60,"SHIPFRAME = " + game_player_frame
  964.         Text 0,80,"CO-ORDS = " + Int(PLAYER_X)
  965.         Text 140,80," , " 
  966.         Text 160,80,Int(PLAYER_Y)
  967.         Text 0,120, "SCORE = " + PLAYER_SCORE
  968.  
  969.         ;this debug code counts how many bullets are "active" in the array (their 'style' - bullets(i,4) is not 0
  970.         ;this was useful for deciding how big the array needed to be for the game, i.e.: how many bullets array
  971.         ;containers would be in use at any one time.
  972.         ;in reality, during the game, this value rarely gets above 100 active bullets,
  973.         ;but I kept the "available" bullets (bulletnum) at 500 anyway.
  974.         
  975.         ;if you needed better performance, then decreasing the value of "bulletnum" might increase the speed of the program!
  976.         bulletcount = 0
  977.         For i = 0 To bulletnum-1
  978.             If bullets(i,4) > 0 Then
  979.                 bulletcount = bulletcount + 1
  980.             End If
  981.         Next
  982.         Text 0,160, "BULLETS = " + bulletcount
  983.     End If
  984.     
  985.     ;just like in "menu_draw_update()", the user can press a key which just makes the value of "FLAG_SCREENSAVE" equal 1.
  986.     ;when the code gets to here, it saves out the named Buffer as a BMP picture.
  987.     If FLAG_SAVESCREEN=1 Then
  988.         SaveBuffer (BackBuffer(),"CRGameScreen.bmp")
  989.         FLAG_SAVESCREEN = 0
  990.     End If 
  991.     
  992.     Flip                    ;as before in "menu_draw_update()", FLIP everything we've just drawn on the backbuffer and show it on the frontbuffer, i.e.: your monitor!!
  993. End Function
  994.  
  995. ;a little function which randomizes the x and y coordinates of each version of the "stars" Type, plus it's "depth" property
  996. Function game_stars_randomize()
  997.     For star.stars=Each stars
  998.         star\x=Rnd(-5,SCREEN_WIDTH)            ;create random x and y positions for all the stars
  999.         star\y=Rnd(-5,SCREEN_HEIGHT)
  1000.         star\depth=Rnd(1,5)                    ;the depth of the stars results in our sexy parallex effect
  1001.     Next
  1002. End Function
  1003.  
  1004. ;an even littler function which just gives us random x and y coordinates for the player.
  1005. Function game_player_randomize()
  1006.     PLAYER_X = Rand(0,GAME_AREA_X)
  1007.     PLAYER_Y = Rand(0,GAME_AREA_Y)
  1008. End Function
  1009.  
  1010.  
  1011. ;This is the last function and it's MARVELLOUS! :)
  1012. ;This is the type of function that you should proactively *try* to write, because they're incredibly simple, yet incredibly effective
  1013. ;and they impress the girls, I can tell you... Um.. No.. That's a lie..
  1014.  
  1015. ;anyway the beauty of this function is that when you call it in the code above, you "feed" it some parameters.
  1016. ;this one is expecting an X Coordinate, a Y Coordinate, an Angle value, a Speed value and a Style value.
  1017. ;it doesn't care who or what they refer to, it just knows that it wants 5 numbers to work with.
  1018.  
  1019. ;So, when a player requires two bullets to be made, I just give it "PLAYER_X, PLAYER_Y, PLAYER_ANGLE,
  1020. ;PLAYER_SPEED and 1 (which just makes sure the correct bullet AnimImage is used!)
  1021.  
  1022. ;When an enemy needs a bullet, I just give it "Enemy X, Enemy Y, Enemy Angle, Enemy Speed, 2"
  1023.  
  1024. ;the createbullet() function does the rest and "produces" 2 bullets on the screen, starting at the end of the calling ship's laser.. BUT THAT'S ALL..
  1025. ;After the bullet has been created, its "life" is calculated in another part of the code (it's x and y coordinates are altered based on the original angle and speed
  1026. ;calculated in this function..) Enjoy
  1027.  
  1028. Function createbullet(x,y,angle,speed,style) ;creates 2 bullets starting on the end of a ship's lasers.
  1029.  
  1030.     ;there are "bulletnum" containers available in the "bullets()" array.
  1031.     ;if we've reached the maximum number of bullets, then the very first
  1032.     ;'bullet' will be overwritten with this new bullet. 
  1033.     ;We do this by wrapping "nextbullet" back to 0, when it reaches bulletnum
  1034.     If nextbullet = bulletnum-1 Then
  1035.         nextbullet = 0
  1036.     End If
  1037.     
  1038.     ;we want to create a bullet for the RIGHT laser of a ship
  1039.     ;by messing with the angleoffset value during debugging, I was able to come up with the
  1040.     ;correct values that looked right on screen (30 for this angle and 28 for the next calculation)
  1041.     angleoffset = angle - 30
  1042.     bullets(nextbullet,0) = x + 28*Cos(angleoffset)        ;this sets the x and y pixel offset from the ship's game coordinates
  1043.     bullets(nextbullet,1) = y + 28*Sin(angleoffset)        ;in this case 28*Cos/Sin of the angle offset
  1044.  
  1045.     ;these next bits are just setting the origin of the bullets, including it's start position, speed and angle
  1046.     ;this is so the bullets can fly independently of the PLAYER's ship's Angle and speed (unlike everything else in the game)
  1047.     bullets(nextbullet,2) = angle
  1048.     If speed <= 0 Then                        ;this bit essentially stops the player catching up to his bullets, or bullets flying backwards
  1049.         bullets(nextbullet,3) = 25            ;if the ship is still, or moving backwards, then a bullet fires off at a speed of 25
  1050.     Else
  1051.         bullets(nextbullet,3) = speed + 25    ;otherwise, if a ship is moving forwards, then the bullet flys off at a speed of 25, PLUS the ship's speed
  1052.     End If
  1053.  
  1054.     bullets(nextbullet,4) = style                    ;used to decide which bullet AnimImage should be used
  1055.     bullets(nextbullet,5) = 0                            ;used to keep track of the frame of animation a bullet is on
  1056.     bullets(nextbullet,6) = bullets(nextbullet,0)        ;used to know where a bullet began it's life in x and y coordinates
  1057.     bullets(nextbullet,7) = bullets(nextbullet,1)
  1058.     nextbullet = nextbullet+1                        ;we've successfully created a bullet (whose 'life' from now on will be calculated back
  1059.                                                     ;in "game_loop_update()", so now we move the "nextbullet" value on by 1
  1060.                                                     ;ready for creation of the next bullet!
  1061.  
  1062.  
  1063.  
  1064.     If nextbullet = bulletnum-1 Then                    ;exactly the same process, but with a 120 degree offset for the left hand laser
  1065.         nextbullet = 0
  1066.     End If
  1067.     angleoffset = angle - 150
  1068.     bullets(nextbullet,0) = x + 28*Cos(angleoffset)
  1069.     bullets(nextbullet,1) = y + 28*Sin(angleoffset)
  1070.     bullets(nextbullet,2) = angle
  1071.     If speed <= 0 Then
  1072.         bullets(nextbullet,3) = 25
  1073.     Else
  1074.         bullets(nextbullet,3) = speed + 25
  1075.     End If
  1076.     bullets(nextbullet,4) = style
  1077.     bullets(nextbullet,5) = 0
  1078.     bullets(nextbullet,6) = bullets(nextbullet,0)
  1079.     bullets(nextbullet,7) = bullets(nextbullet,1)
  1080.     nextbullet = nextbullet+1
  1081. End Function